// 基本数据类型
class bs_crt_uint8 {
    constructor(_value = 0) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 1; }
    static new_helper() { return new bs_crt_uint8(); }

    length() { return 1; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_u_i_8(this.value__, false);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_u_i_8(false);
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}
class bs_crt_uint16 {
    constructor(_value = 0) {
      this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 2; }
    static new_helper() { return new bs_crt_uint16(); }
    
    length() { return 2; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_u_i_16(this.value__, false);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_u_i_16(false);
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}
class bs_crt_uint32 {
    constructor(_value = 0) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 4; }
    static new_helper() { return new bs_crt_uint32(); }

    length() { return 4; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_u_i_32(this.value__, false);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_u_i_32(false);
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}
class bs_crt_int8 {
    constructor(_value = 0) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 1; }
    static new_helper() { return new bs_crt_int8(); }

    length() { return 1; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_u_i_8(this.value__, true);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_u_i_8(true);
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}
class bs_crt_int16 {
    constructor(_value = 0) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 2; }
    static new_helper() { return new bs_crt_int16(); }

    length() { return 2; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_u_i_16(this.value__, true);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_u_i_16(true);
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}
class bs_crt_int32 {
    constructor(_value = 0) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 4; }
    static new_helper() { return new bs_crt_int32(); }

    length() { return 4; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_u_i_32(this.value__, true);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_u_i_32(true);
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}
class bs_crt_int64 {
    constructor(_value = 0) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 8; }
    static new_helper() { return new bs_crt_int64(); }

    length() { return 8; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_i_64(this.value__);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_i_64();
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}
class bs_crt_float32 {
    constructor(_value = 0) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 4; }
    static new_helper() { return new bs_crt_float32(); }

    length() { return 4; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_f_32(this.value__);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_f_32(true);
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}
class bs_crt_float64 {
    constructor(_value = 0) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static type_length() { return 8; }
    static new_helper() { return new bs_crt_float64(); }

    length() { return 8; }

    serialize(_stream_help) {
        if(undefined == this.value__ || null == this.value__) {
            this.value__ = 0;
        }
        return _stream_help.write_f_64(this.value__);
    }
    build(_stream_help) {
        let l_value = _stream_help.read_f_64(true);
        if (null == l_value) {
            return false;
        }
        this.value__ = l_value;
        return true;
    }
}

class bs_string_byte {
    static string_to_byte(_string) {
        let l_result = [];
        if (undefined == _string || null == _string) {
            return l_result;
        }
        let l_value;
        for (let i = 0; i < _string.length; ++i){
            l_value = _string.charCodeAt(i);
            if(l_value >= 0x010000 && l_value <= 0x10FFFF){  
                l_result.push(((l_value >> 18) & 0x07) | 0xF0);
                l_result.push(((l_value >> 12) & 0x3F) | 0x80);  
                l_result.push(((l_value >> 6) & 0x3F) | 0x80);  
                l_result.push((l_value & 0x3F) | 0x80);  
            }else if(l_value >= 0x000800 && l_value <= 0x00FFFF){  
                l_result.push(((l_value >> 12) & 0x0F) | 0xE0);  
                l_result.push(((l_value >> 6) & 0x3F) | 0x80);  
                l_result.push((l_value & 0x3F) | 0x80);  
            }else if(l_value >= 0x000080 && l_value <= 0x0007FF){  
                l_result.push(((l_value >> 6) & 0x1F) | 0xC0);  
                l_result.push((l_value & 0x3F) | 0x80);  
            }else{  
                l_result.push(l_value & 0xFF);  
            }
        }
        return l_result; 
    }
    static byte_to_string(_byte) {
        let l_result = '';
        let l_value;
        for (let i = 0; i < _byte.length; i++) {
            if(0 == _byte[i]) {
                break;
            }
            l_value = _byte[i].toString(2);
            let l_match = l_value.match(/^1+?(?=0)/);
            if(l_match && l_value.length == 8) {  
                let l_bytes_length = l_match[0].length;  
                let l_store = _byte[i].toString(2).slice(7 - l_bytes_length);
                if(l_bytes_length + i > _byte.length) {
                    break;
                }  
                for(let st = 1; st < l_bytes_length; st++) {  
                    l_store += _byte[st + i].toString(2).slice(2);  
                }  
                l_result += String.fromCharCode(parseInt(l_store, 2));  
                i += l_bytes_length - 1;  
            } else {  
                l_result += String.fromCharCode(_byte[i]);  
            }  
        }
        return l_result;
    }
}

// 字符串
class bs_ustring_t {
    constructor(_value) {
        this.value__ = _value;
    }

    get value_() { return this.value__; }
    set value_(value) { this.value__ = value; }

    static new_helper() { return new bs_ustring_t(); }

    length() { 
        let l_length = 0;
        l_length += bs_crt_uint32.type_length();
        if (undefined == this.value__ || null == this.value__ || 0 == this.value__.length) {
            return l_length;
        }
        l_length += bs_string_byte.string_to_byte(this.value__).length;
        return l_length;
    }

    serialize(_stream_help) {
        // 长度
        let l_element_count = new bs_crt_uint32();
        if (undefined == this.value__ || null == this.value__ || 0 == this.value__.length) {
            l_element_count.value_ = 0;
            return l_element_count.serialize(_stream_help);
        }
        let l_bytes = bs_string_byte.string_to_byte(this.value__);
        l_element_count.value_ = l_bytes.length;
        if (!l_element_count.serialize(_stream_help)) {
            return false;
        }

        // 数据
        let l_uint8_view = _stream_help.uint8_view(l_bytes.length);
        if (null == l_uint8_view) {
            return false;
        }
        for(let i = 0; i < l_bytes.length; ++i) {
            l_uint8_view[i] = l_bytes[i];
        }
        return true;
    }
    build(_stream_help) {
        // 长度
        let l_element_count = new bs_crt_uint32();
        if (!l_element_count.build(_stream_help)) {
            return false;
        }
        if (0 == l_element_count.value_) {
            this.value__ = "";
            return true;
        }
        // 数据
        let l_uint8_view = _stream_help.uint8_view(l_element_count.value_);
        if (null == l_uint8_view) {
            return false;
        }
        this.value__ = bs_ustring_t.byte_to_string(l_uint8_view);
        return true;
    }
}

// 数组:简单类型
class bs_list_st {
    constructor(_new_function) {
        this.new_function__ = _new_function;
        this.list__ = [];
    }

    get value_() {
        let l_result = [];
        if(undefined == this.list__ || null == this.list__) {
            return l_result;
        }
        for(let l_index in this.list__) {
            l_result[l_index] = this.list__[key];
        }
        return l_result;
    }
    set value_(_value) {
        this.list__ = [];
        if(undefined == _value || null == _value) {
            return;
        }
        for(let l_index in _value) {
            this.list__[l_index] = _value[l_index];
        } 
    }

    length() {
        let l_length = 0;
        l_length += bs_crt_uint32.type_length();
        if(undefined == this.list__ || null == this.list__ || 0 == this.list__.length) {
            return l_length;
        }
        let l_bs_member = this.new_function__();
        l_length += l_bs_member.length() * this.list__.length;
        return l_length;
    }

    serialize(_stream_help) {
        let l_element_count = new bs_crt_uint32();
        l_element_count.value_ = (undefined == this.list__ || null == this.list__) ? 0 : this.list__.length;
        if (!l_element_count.serialize(_stream_help)) {
            return false;
        }
        if(undefined == this.list__ || null == this.list__ || 0 == this.list__.length) {
            return true;
        }
        // 数据
        let l_bs_member = this.new_function__();
        for (let i = 0; i < this.list__.length; ++i) {
            l_bs_member.value_ = this.list__[i];
            if (!l_bs_member.serialize(_stream_help)) {
                return false;
            }
        }
        return true;
    }

    build(_stream_help) {
        let l_element_count = new bs_crt_uint32();
        if (!l_element_count.build( _stream_help )) {
            return false;
        }
        if (0 == l_element_count.value_) {
            this.list__ = [];
            return true;
        }

        let l_bs_member = this.new_function__();
        this.list__ = [];
        for (let i = 0; i < l_element_count.value_; ++i) {
            if (!l_bs_member.build(_stream_help)) {
                return false;
            }
            this.list__[i] = l_bs_member.value_;
        }
        return true;
    }
}

// 数组:自定义类型
class bs_list_ot {
    constructor(_new_function) {
        this.new_function__ = _new_function;
        this.list__ = [];
    }

    get value_() {
        let l_result = [];
        if (undefined == this.list__ || null == this.list__) {
            return l_result;
        }
        for (let l_index in this.list__) {
            l_result[l_index] = this.list__[l_index];
        }
        return l_result;
    }
    set value_(_value) {
        this.list__ = [];
        if (undefined == _value || null == _value) {
            return;
        }
        for(let l_index in _value) {
            this.list__[l_index] = _value[l_index];
        }
    }

    length() {
        let l_length = 0;
        l_length += bs_crt_uint32.type_length();
        if (undefined === this.list__ || null === this.list__ || 0 === this.list__.length) {
            return l_length;
        }
        for (let i = 0; i < this.list__.length; ++i) {
            l_length += this.list__[i].length();
        }
        return l_length;
    }

    serialize(_stream_help) {
        // 长度
        let l_element_count = new bs_crt_uint32();
        l_element_count.value_ = (undefined == this.list__ || null == this.list__) ? 0 : this.list__.length;
        if (!l_element_count.serialize(_stream_help)) {
            return false;
        }
        if (undefined == this.list__ || null == this.list__ || 0 == this.list__.length) {
            return true;
        }
        // 数据
        for (let i = 0; i < this.list__.length; ++i) {
            if (!this.list__[i].serialize(_stream_help)) {
                return false;
            }
        }
        return true;
    }

    build(_stream_help) {
        let l_element_count = new bs_crt_uint32();
        if (!l_element_count.build(_stream_help)) {
            return false;
        }
        if (0 == l_element_count.value_) {
            this.list__ = [];
            return true;
        }

        this.list__ = [];
        for (let i = 0; i < l_element_count.value_; ++i) {
            let l_bs_member = this.new_function__();
            if (!l_bs_member.build(_stream_help)) {
                return false;
            }
            this.list__[i] = l_bs_member;
        }
        return true;
    }
}

// 消息控制结构，所以协议的父类
class bs_message_t {
    constructor() {}

    length() {
        let l_length = bs_crt_uint32.type_length();
        if (undefined != this['child_length'] && null != this['child_length']) {
            l_length += this.child_length();
        }
        return l_length;
    }
    serialize(_stream_help) {
        let l_class_length = new bs_crt_uint32(this.length() - bs_crt_uint32.type_length());
        if (!l_class_length.serialize(_stream_help)) {
            return false;
        }
        if (undefined == this['child_serialize'] || null == this['child_serialize']) {
            return true;
        }
        return this.child_serialize(_stream_help);
    }
    build(_stream_help) {
        let l_class_length = new bs_crt_uint32(0);
        if (!l_class_length.build(_stream_help)) {
            return false;
        }
        if (undefined == this['child_build'] || null == this['child_build']) {
            return true;
        }
        let l_child_stream = _stream_help.child_stream(l_class_length.value_);
        if (null == l_child_stream) {
            return false;
        }
        this.child_build(l_child_stream);
        // 此处失败只是一个子结构build失败，存在字段多了的情况，忽略
        return true;
    }
}

// 空结构
class bs_null_t extends bs_message_t {
    constructor() {
      super();
    }

    static new_helper() { return new bs_null_t(); }

    child_length() { return 0; }
    child_serialize(_stream_help) { return true; }
    child_build(_stream_help) { return true; }
}

window['namespace'] = window['namespace'] || {};
window['namespace']['build_serialize'] = window['namespace']['build_serialize'] || {};
let build_serialize = window['namespace']['build_serialize'];

build_serialize['bs_crt_uint8'] = bs_crt_uint8;
build_serialize['bs_crt_uint16'] = bs_crt_uint16;
build_serialize['bs_crt_uint32'] = bs_crt_uint32;
build_serialize['bs_crt_int8'] = bs_crt_int8;
build_serialize['bs_crt_int16'] = bs_crt_int16;
build_serialize['bs_crt_int32'] = bs_crt_int32;
build_serialize['bs_crt_int64'] = bs_crt_int64;
build_serialize['bs_crt_float32'] = bs_crt_float32;
build_serialize['bs_crt_float64'] = bs_crt_float64;
build_serialize['bs_ustring_t'] = bs_ustring_t;
build_serialize['bs_list_st'] = bs_list_st;
build_serialize['bs_list_ot'] = bs_list_ot;
build_serialize['bs_message_t'] = bs_message_t;
build_serialize['bs_null_t'] = bs_null_t;

